//
//  SPMacros.h
//  ShandongPoker
//
//  Created by Developer on 2025-01-08.
//  Copyright © 2025 ShandongPoker. All rights reserved.
//

#ifndef SPMacros_h
#define SPMacros_h

#pragma mark - 单例宏

#define SP_SINGLETON_INTERFACE(className) \
+ (instancetype)sharedInstance;

#define SP_SINGLETON_IMPLEMENTATION(className) \
+ (instancetype)sharedInstance { \
    static className *_instance = nil; \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
        _instance = [[className alloc] init]; \
    }); \
    return _instance; \
}

#pragma mark - 属性合成宏

#define SP_SYNTHESIZE_READONLY(type, name) \
@property (nonatomic, assign, readonly) type name;

#define SP_SYNTHESIZE_STRONG(type, name) \
@property (nonatomic, strong) type name;

#define SP_SYNTHESIZE_WEAK(type, name) \
@property (nonatomic, weak) type name;

#define SP_SYNTHESIZE_COPY(type, name) \
@property (nonatomic, copy) type name;

#pragma mark - 懒加载宏

#define SP_LAZY_LOAD(type, name, initCode) \
- (type)name { \
    if (!_##name) { \
        _##name = initCode; \
    } \
    return _##name; \
}

#pragma mark - 通知宏

#define SP_POST_NOTIFICATION(name, object, userInfo) \
[[NSNotificationCenter defaultCenter] postNotificationName:name object:object userInfo:userInfo]

#define SP_ADD_OBSERVER(observer, selector, name, object) \
[[NSNotificationCenter defaultCenter] addObserver:observer selector:selector name:name object:object]

#define SP_REMOVE_OBSERVER(observer) \
[[NSNotificationCenter defaultCenter] removeObserver:observer]

#pragma mark - 错误处理宏

#define SP_ERROR(domain, code, description) \
[NSError errorWithDomain:domain code:code userInfo:@{NSLocalizedDescriptionKey: description}]

#define SP_GAME_ERROR(code, description) \
SP_ERROR(SPGameErrorDomain, code, description)

#pragma mark - 数值验证宏

#define SP_CLAMP(value, min, max) \
MAX(min, MIN(max, value))

#define SP_IS_VALID_CHIPS(chips) \
(chips >= 0)

#define SP_IS_VALID_PLAYER_COUNT(count) \
(count >= SP_MIN_PLAYERS && count <= SP_MAX_PLAYERS)

#pragma mark - 字符串宏

#define SP_STRING_IS_EMPTY(str) \
(str == nil || [str isEqualToString:@""])

#define SP_STRING_IS_NOT_EMPTY(str) \
(!SP_STRING_IS_EMPTY(str))

#pragma mark - 数组宏

#define SP_ARRAY_IS_EMPTY(array) \
(array == nil || array.count == 0)

#define SP_ARRAY_IS_NOT_EMPTY(array) \
(!SP_ARRAY_IS_EMPTY(array))

#define SP_SAFE_ARRAY_ACCESS(array, index) \
(array && index >= 0 && index < array.count ? array[index] : nil)

#pragma mark - 时间宏

#define SP_CURRENT_TIMESTAMP \
[[NSDate date] timeIntervalSince1970]

#pragma mark - 格式化宏

#define SP_FORMAT_CHIPS(chips) \
[NSString stringWithFormat:@"¥%@", [SPNumberFormatter formatNumber:@(chips)]]

#define SP_FORMAT_PERCENTAGE(value) \
[NSString stringWithFormat:@"%.1f%%", value * 100]

#pragma mark - 动画宏

#define SP_ANIMATE_WITH_DURATION(duration, animations) \
[UIView animateWithDuration:duration animations:animations]

#define SP_ANIMATE_WITH_COMPLETION(duration, animations, completion) \
[UIView animateWithDuration:duration animations:animations completion:completion]

#pragma mark - 约束宏

#define SP_CONSTRAINT_EQUAL(view1, attr1, view2, attr2, constant) \
[NSLayoutConstraint constraintWithItem:view1 attribute:attr1 relatedBy:NSLayoutRelationEqual toItem:view2 attribute:attr2 multiplier:1.0 constant:constant]

#define SP_CONSTRAINT_CENTER_X(view, superview) \
SP_CONSTRAINT_EQUAL(view, NSLayoutAttributeCenterX, superview, NSLayoutAttributeCenterX, 0)

#define SP_CONSTRAINT_CENTER_Y(view, superview) \
SP_CONSTRAINT_EQUAL(view, NSLayoutAttributeCenterY, superview, NSLayoutAttributeCenterY, 0)

#pragma mark - 调试宏

#ifdef DEBUG
#define SP_ASSERT(condition, description) \
NSAssert(condition, description)

#define SP_ASSERT_MAIN_THREAD() \
SP_ASSERT([NSThread isMainThread], @"This method must be called on the main thread")

#define SP_ASSERT_NOT_NIL(object) \
SP_ASSERT(object != nil, @"Object should not be nil")
#else
#define SP_ASSERT(condition, description)
#define SP_ASSERT_MAIN_THREAD()
#define SP_ASSERT_NOT_NIL(object)
#endif

#endif /* SPMacros_h */